﻿using ApisixSDK.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace ApisixSDK.Admin.model
{
    public class Upstream : BaseModel
    {
        /// <summary>
        /// [必需]哈希表或数组。当它是哈希表时，内部元素的 key 是上游机器地址列表，格式为地址 + （可选的）端口，其中地址部分可以是 IP 也可以是域名
        /// <code>不能和 service_name 一起用</code>
        /// <code>"nodes": {"host:80": 100}, 上游机器地址列表，格式为`地址 + 端口`# 等价于 "nodes": { {"host":"host", "port":80, "weight": 100} },</code>
        /// </summary>
        [JsonProperty(propertyName: "nodes")]
        public IDictionary<string, int> Nodes { get; set; }

        /// <summary>
        /// [必需]服务发现时使用的服务名，见集成服务发现注册中心
        /// <code>不能和 nodes 一起用</code>
        /// </summary>
        [JsonProperty(propertyName: "service_name")]
        public string ServiceName { get; set; }
        /// <summary>
        /// [必需]服务发现类型，见集成服务发现注册中心
        /// <code>如果设置了 service_name 则必需有此配置</code>
        /// </summary>
        [JsonIgnore]
        public DiscoveryType DiscoveryType { get; set; }

        /// <summary>
        /// [禁止手动赋值],请通过设置 DiscoveryType赋值
        /// </summary>
        [JsonProperty(propertyName: "discovery_type")]
        public string DiscoveryString
        {
            get { return this.DiscoveryType.ToString().ToLower(); }
            set
            {
                DiscoveryType g;
                this.DiscoveryType = Enum.TryParse(value, true, out g) ? g : DiscoveryType.Eureka;
            }
        }

        /// <summary>
        /// [必需]负载均衡算法 roundrobin,chash,ewma,least_conn
        /// </summary>
        [JsonIgnore]
        public SLBType Type { get; set; }

        /// <summary>
        /// [禁止手动赋值],请通过设置 Type 赋值
        /// </summary>
        [JsonProperty(propertyName: "type")]
        public string TypeString
        {
            get { return this.Type.ToString().ToLower(); }
            set
            {
                SLBType g;
                this.Type = Enum.TryParse(value, true, out g) ? g : SLBType.Roundrobin;
            }
        }
        /// <summary>
        /// [暂时不支持]该选项只有类型是 chash 才有效。
        /// </summary>
        [JsonProperty(propertyName: "key")]
        public string Key { get; set; }

        /// <summary>
        /// 使用底层的 Nginx 重试机制将请求传递给下一个上游，默认启用重试且次数为后端可用的 node 数量。如果指定了具体重试次数，它将覆盖默认值。0 代表不启用重试机制。
        /// </summary>
        [JsonProperty(propertyName: "retries")]
        public int? Retries { get; set; }
        /// <summary>
        /// 设置连接、发送消息、接收消息的超时时间
        /// </summary>
        [JsonProperty(propertyName: "timeout")]
        public Timeout Timeout { get; set; }

        /// <summary>
        /// 上游服务描述、使用场景等。
        /// </summary>
        [JsonProperty(propertyName: "desc")]
        public string Desc { get; set; }
        /// <summary>
        /// 标识上游服务名称、使用场景等。
        /// </summary>
        [JsonProperty(propertyName: "name")]
        public string Name { get; set; }

        /// <summary>
        /// [可选]配置健康检查的参数，详细可参考health-check
        /// </summary>
        [JsonProperty(propertyName: "checks")]
        public Health_Checker Checker { get; set; }
    }

    public enum DiscoveryType
    {
        DNS,
        Consul_KV,
        Nacos,
        Eureka
    }
    /// <summary>
    /// 负载均衡枚举
    /// </summary>
    public enum SLBType
    {
        /// <summary>
        /// 带权重的 roundrobin
        /// </summary>
        Roundrobin,
        /// <summary>
        /// 一致性哈希
        /// </summary>
        Chash,
        /// <summary>
        /// 选择延迟最小的节点，计算细节参考 https://en.wikipedia.org/wiki/EWMA_chart
        /// </summary>
        Ewma,
        /// <summary>
        /// 选择 (active_conn + 1) / weight 最小的节点。注意这里的 active connection 概念跟 Nginx 的相同：它是当前正在被请求使用的连接。
        /// </summary>
        Least_conn
    }

}
